package cn.zoujiedev.netty.core.encoder;

import cn.zoujiedev.netty.core.bean.Header;
import cn.zoujiedev.netty.core.bean.NettyMessage;
import cn.zoujiedev.netty.core.serialization.HessianEncoder;
import cn.zoujiedev.netty.core.serialization.ObjectEncoder;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @Classname NettyMessageEncoder
 * @Description
 * @Date 2022-11-3 13:41
 * @Created by zoujie
 */
public class NettyMessageEncoder extends MessageToMessageEncoder<NettyMessage> {

  private ObjectEncoder encoder;

  public NettyMessageEncoder(ObjectEncoder encoder){
    this.encoder = encoder;
  }

  @Override
  protected void encode(ChannelHandlerContext ctx, NettyMessage msg, List<Object> list) throws Exception {
    if(msg == null || msg.getHeader() == null){
      throw new Exception("the encode message or message header can not be null");
    }

    ByteBuf sendBuf = Unpooled.buffer();

    Header header = msg.getHeader();
    //写入header基础属性
    sendBuf.writeInt(header.getCrcCode());
    sendBuf.writeInt(header.getLength());
    sendBuf.writeLong(header.getSessionId());
    sendBuf.writeByte(header.getType());
    sendBuf.writeByte(header.getPriority());

    //写入header attachment 数量
    sendBuf.writeInt(header.getAttachment().size());

    Set<Entry<String, Object>> entries = header.getAttachment().entrySet();
    for (Entry<String,Object> entry : entries){
      String key = entry.getKey();
      Object value = entry.getValue();

      byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
      sendBuf.writeInt(keyBytes.length);
      sendBuf.writeBytes(keyBytes);

      encoder.encode(value,sendBuf);
    }

    //写入body
    Object body = msg.getBody();
    if(body != null){
      encoder.encode(body,sendBuf);
    }else {
      sendBuf.writeInt(0);
    }

    //设置最终的字节长度
    sendBuf.setInt(4,sendBuf.readableBytes());

    list.add(sendBuf);
  }
}
